#include "../src/parser/parsercc.hpp"
#include <iostream>
#include <fstream>

using namespace std;

/**
 * 这是一个从CSV格式的LR(1)分析表构建parser的例子，从./simpleC_table.csv读取
 * 分析表，从../testcase/读取词法和文法定义，并且会读取../testcase/simpleC.c
 * 进行语法分析，将结果输出到../output/文件夹中
 */
int main() {
    cout << "\n\n";
    ifstream lexIn;
    fstream csvIn;
    ifstream syntaxIn;
    ifstream astConfigIn;
    ifstream sourceIn;
    fstream parseOut;
    fstream astJsonOut;
    fstream astTxtOut;
    if (!fs::exists("../output")) {
        fs::create_directory("../output");
    }
    const string TEST_BASE = "../testcase/simpleC/";
    const string OUT_BASE = "../output/simpleC/";
    __OPEN_AND_CHECK(lexIn, TEST_BASE + "simpleC_lex.json", false);
    __OPEN_AND_CHECK(csvIn, "./simpleC_table.csv", false);
    __OPEN_AND_CHECK(syntaxIn, TEST_BASE + "simpleC_syntax.txt", false);
    __OPEN_AND_CHECK(astConfigIn, TEST_BASE + "simpleC_ast_conf.json", false);
    __OPEN_AND_CHECK(sourceIn, TEST_BASE + "simpleC.c", false);
    __OPEN_AND_CHECK(parseOut, OUT_BASE + "simpleC_parse_tree.txt", true);
    __OPEN_AND_CHECK(astJsonOut, OUT_BASE + "simpleC_AST.json", true);
    __OPEN_AND_CHECK(astTxtOut, OUT_BASE + "simpleC_AST.txt", true);
    // ---------------------------------------------------------------------- //
    // Lex
    MyLexer lexer = buildLexerFromJson(lexIn);
    auto tokens = lexer.lex(sourceIn);
    // Parse
    MyParser parser;
    parser.buildParserFromCsvParseTable(csvIn, syntaxIn);
    MyParser::PtrParseTreeNode parseTree;
    parseTree = parser.parse(tokens);
    // Print parse tree
    parser.printParseTree(parseOut, parseTree);
    cout << "++++ Parse tree saved at ./output/simpleC_parse_tree.txt\n";
    // Print AST
    ASTConfig config = ASTConfig::configWithJson(astConfigIn);
    PtrASTNode ast;
    ast = ASTNode::buildAST(parseTree, config);
    ast->printAST(astTxtOut);
    FifoJson fifoJ;
    astJsonOut << std::setw(2) << my_json_wrap(ast) << endl;
    cout << "++++ AST saved at ./output/simpleC_AST.txt\n";
    // ---------------------------------------------------------------------- //
    lexIn.close();
    syntaxIn.close();
    astConfigIn.close();
    sourceIn.close();
    parseOut.close();
    astJsonOut.close();
    astTxtOut.close();
    system("pause");
}
